/**
 * IsvRequestParamAssembleFactory.java
 * author: yujiakui
 * 2017年8月29日
 * 下午4:38:46
 */
package com.ctim.service.component.assemble;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import com.ctim.common.exception.PcsRunTimeException;
import com.ctim.service.enums.IsvRequestParamAssembleTypeEnum;
import com.google.common.collect.Maps;

/**
 * @author yujiakui
 *
 *         下午4:38:46
 *
 *         渠道请求参数组装器工厂
 */
@Component
public class IsvRequestParamAssembleFactory implements ApplicationContextAware, InitializingBean {

	/** 组装器map */
	private static Map<IsvRequestParamAssembleTypeEnum, IsvRequestParamAssemble> assembleMap = Maps
			.newHashMap();

	/** spring 上下文 */
	private ApplicationContext applicationContext;

	/**
	 * 根据参数获取对应的组装器类型
	 *
	 * @param type
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static IsvRequestParamAssemble getAssembleByType(IsvRequestParamAssembleTypeEnum type) {
		IsvRequestParamAssemble isvRequestParamAssemble = assembleMap.get(type);
		if (null == isvRequestParamAssemble) {
			throw new PcsRunTimeException(
					MessageFormat.format("类型type={0}对应的校验器不存在map={1}", type, assembleMap));
		}
		return isvRequestParamAssemble;
	}

	/*
	 *
	 * @see
	 * org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void afterPropertiesSet() throws Exception {

		// 获取实现validator接口的bean，然后将这种bean注入到工厂的map中
		Map<String, IsvRequestParamAssemble> assembleBeanMap = applicationContext
				.getBeansOfType(IsvRequestParamAssemble.class);
		// 防止并发情况注入
		Map<IsvRequestParamAssembleTypeEnum, IsvRequestParamAssemble> tempAssembleMap = Maps
				.newHashMap(assembleMap);
		for (Map.Entry<String, IsvRequestParamAssemble> entryEle : assembleBeanMap.entrySet()) {
			IsvRequestParamAssemble isvRequestParamAssemble = entryEle.getValue();
			List<IsvRequestParamAssembleTypeEnum> validatorTypeEnums = isvRequestParamAssemble
					.getAssembleType();
			for (IsvRequestParamAssembleTypeEnum assembleType : validatorTypeEnums) {
				IsvRequestParamAssemble tempAssemble = tempAssembleMap.get(assembleType);
				if (null != tempAssemble) {
					if (!tempAssemble.equals(isvRequestParamAssemble)) {
						throw new PcsRunTimeException(
								MessageFormat.format("在组装器工厂中进行注入得到同一个type={0}对应多个组装器对象={1},{2}",
										assembleType, isvRequestParamAssemble, tempAssemble));
					}
				} else {
					tempAssembleMap.put(assembleType, isvRequestParamAssemble);
				}
			}

		}

		assembleMap = tempAssembleMap;
	}

	/*
	 *
	 * @see
	 * org.springframework.context.ApplicationContextAware#setApplicationContext
	 * (org.springframework.context.ApplicationContext)
	 */
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}
